package cn.zyl.quartz.service.impl;

import cn.zyl.quartz.bean.JobParameter;
import cn.zyl.quartz.service.TaskService;
import cn.zyl.quartz.typeEnum.StrategyEnum;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: zhaoyunlong
 * @Description: 定时任务的操作类
 * @Date: Create in 10:13 2018/12/21
 */
@Service
public class TaskServiceImpl implements TaskService {

    private static AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    private static Scheduler scheduler = (Scheduler) context.getBean("scheduler");

    @Override
    public List<JobParameter> getAllJob() {
        List<JobParameter> jobParameters = new ArrayList<>();
        try {
            for (String groupName : scheduler.getJobGroupNames()) {
                JobParameter jobParameter = new JobParameter();
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
                    jobParameter.setJobName(jobKey.getName());
                    jobParameter.setJobGroup(jobKey.getGroup());
                    //通过jobKey获取 触发器
                    List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);

                    //下次点火时间
                    jobParameter.setNextFireTime(triggers.get(0).getNextFireTime().toString());

                    //当前状态
                    TriggerKey triggerKey = TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
                    jobParameter.setStatus(triggerState.toString());
                }
                jobParameters.add(jobParameter);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobParameters;
    }

    @Override
    public void startAllJob() {
        try{
            scheduler.start();
        } catch ( SchedulerException e ){
            e.printStackTrace();
        }
    }

    @Override
    public Trigger getTrigger(String trigger, String triggerGroup) {
        CronTrigger cronTrigger = null;
        try {
            cronTrigger = (CronTrigger) scheduler.getTrigger(new TriggerKey(trigger, triggerGroup));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return cronTrigger;
    }

    @Override
    public void addCronJob(JobParameter jobParameter) {
        try {
            Class jobClass = Class.forName(jobParameter.getJobClass());
            JobDetail job = JobBuilder.newJob(jobClass)
                    .withIdentity(jobParameter.getJobName(), jobParameter.getJobGroup())
                    .withDescription(jobParameter.getDescription())
                    .build();

            //向JobDataMap中存储参数
            JobDataMap jobDataMap = job.getJobDataMap();
            for (Map.Entry<String, String> entry : jobParameter.getParam().entrySet()) {
                jobDataMap.put(entry.getKey(), entry.getValue());
            }

            //触发器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobParameter.getCronExpression());


            switch ( jobParameter.getStrategy() ){
                case DoNothing :
                    scheduleBuilder.withMisfireHandlingInstructionDoNothing();
                    break;
                case FireAndProceed:
                    scheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
                    break;
                case IgnoreMisfires:
                    scheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();
                    break;
                default:
                    scheduleBuilder.withMisfireHandlingInstructionDoNothing();
                    break;
            }
            //scheduleBuilder.withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobParameter.getTriggerName(), jobParameter.getTriggerGroup())
                    .startAt(jobParameter.getStartTime())
                    .withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(job, trigger);

            if (scheduler.isStarted()) {
                scheduler.start();
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void addSimpleJob(JobParameter jobParameter) {
        try {
            Class jobClass = Class.forName(jobParameter.getJobClass());
            JobDetail job = JobBuilder.newJob(jobClass)
                    .withIdentity(jobParameter.getJobName(), jobParameter.getJobGroup())
                    .withDescription(jobParameter.getDescription())
                    .build();

            //向JobDataMap中存储参数
            JobDataMap jobDataMap = job.getJobDataMap();
            for (Map.Entry<String, String> entry : jobParameter.getParam().entrySet()) {
                jobDataMap.put(entry.getKey(), entry.getValue());
            }

            SimpleScheduleBuilder simpleSchedule = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds( jobParameter.getRepeatInterval() )
                    .withRepeatCount( jobParameter.getRepeatNum() );

            SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger().withIdentity(jobParameter.getTriggerName(), jobParameter.getTriggerGroup())
                    .startAt( jobParameter.getStartTime() )
                    .endAt( jobParameter.getEndTime() )
                    .withSchedule( simpleSchedule ).build();

            scheduler.scheduleJob( job, simpleTrigger );
        } catch ( ClassNotFoundException e ){
            e.printStackTrace();
        } catch ( SchedulerException e ){
            e.printStackTrace();
        }
    }

    @Override
    public void modifyJobCron(JobParameter jobParameter, String newCronExpression) {
        try{
            TriggerKey triggerKey = TriggerKey.triggerKey( jobParameter.getTriggerName(), jobParameter.getTriggerGroup() );
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger( triggerKey );

            if( trigger == null ){
                return;
            }

            String oldTime = trigger.getCronExpression();
            //如果旧Cron表达式不与新Cron相同
            if( !oldTime.equals( newCronExpression ) ){
                //触发器
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                //触发器名
                triggerBuilder.withIdentity( jobParameter.getTriggerName(), jobParameter.getTriggerGroup() );
                //Cron Expression
                triggerBuilder.withSchedule( CronScheduleBuilder.cronSchedule( newCronExpression ) );
                //创建Trigger对象
                trigger = (CronTrigger ) triggerBuilder.build();
                scheduler.rescheduleJob( triggerKey, trigger );
            }
        } catch ( SchedulerException e ){
            e.printStackTrace();
        }
    }

    @Override
    public void deleteJob(JobParameter jobParameter) {
        try {
            JobKey jobKey = new JobKey(jobParameter.getJobName(), jobParameter.getJobGroup());
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void parseJob(JobParameter jobParameter) {
        try {
            JobKey jobKey = new JobKey(jobParameter.getJobName(), jobParameter.getJobGroup());
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void resumeJob(JobParameter jobParameter) {
        try {
            JobKey jobKey = new JobKey(jobParameter.getJobName(), jobParameter.getJobGroup());
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void pauseAllJob() {
        try {
            scheduler.pauseAll();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void resumeAllJob() {
        try {
            scheduler.resumeAll();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

}


